package com.dzu.gulimall.cart.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.TypeReference;
import com.dzu.common.utils.R;
import com.dzu.gulimall.cart.feign.ProductFeignService;
import com.dzu.gulimall.cart.interceptor.CartInterceptor;
import com.dzu.gulimall.cart.service.CartService;
import com.dzu.gulimall.cart.vo.Cart;
import com.dzu.gulimall.cart.vo.CartItem;
import com.dzu.gulimall.cart.vo.SkuInfoEntity;
import com.dzu.gulimall.cart.vo.UserInfoTo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;

/**
 * @author ZhaoDong
 * @date 2022/7/2 13:39
 * @description gulimall
 */
@Slf4j
@Service
public class CartServiceImpl implements CartService {

    private final String CART_PREFIX = "gulimall:cart:";

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private ProductFeignService productFeignService;

    @Autowired
    private ThreadPoolExecutor threadPoolExecutor;

    @Override
    public CartItem addToCart(Long skuId, Integer count) {

        BoundHashOperations<String, String, String> ops = getCartOps();


        // 购物车没有此商品
        String res = ops.get(skuId.toString());
        if (StrUtil.isEmpty(res)) {
            // 2、 新的商品添加到购物车

            CartItem item = new CartItem();

            CompletableFuture<Void> getSkuInfoTask = CompletableFuture.runAsync(() -> {

                // 1、 远程查询当前要添加商品的信息
                R r = productFeignService.getSkuInfo(skuId);
                SkuInfoEntity skuInfo = r.getData("skuInfo", new TypeReference<SkuInfoEntity>() {
                });

                item.setCount(count);
                item.setImage(skuInfo.getSkuDefaultImg());
                item.setTitle(skuInfo.getSkuTitle());
                item.setSkuId(skuId);
                item.setPrice(skuInfo.getPrice());

            }, threadPoolExecutor);


            // 2、远程查询sku的组合信息.

            CompletableFuture<Void> getSkuSaleAttrValuesTask = CompletableFuture.runAsync(() -> {
                List<String> attrList = productFeignService.getSkuSaleAttrValues(skuId);
                item.setSkuAttr(attrList);

            }, threadPoolExecutor);

            try {
                CompletableFuture.allOf(getSkuInfoTask, getSkuSaleAttrValuesTask).get();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            } catch (ExecutionException e) {
                throw new RuntimeException(e);
            }

            ops.put(skuId.toString(), JSONUtil.toJsonStr(item));

            return item;
        } else {
            // 购物车有 此商品，修改数量
            CartItem item = JSONUtil.toBean(res, CartItem.class);
            item.setCount(item.getCount() + count);

            ops.put(skuId.toString(), JSONUtil.toJsonStr(item));

            return item;
        }
    }

    @Override
    public CartItem getCartItem(Long skuId) {
        BoundHashOperations<String, String, String> ops = getCartOps();
        String str = ops.get(skuId.toString());
        CartItem cartItem = JSONUtil.toBean(str, CartItem.class);
        return cartItem;
    }

    @Override
    public Cart getCart() {
        Cart cart = new Cart();
        UserInfoTo userInfoTo = CartInterceptor.THREAD_LOCAL.get();
        if (userInfoTo.getUserId() == null) {
            // 没登陆
            String key = CART_PREFIX + userInfoTo.getUserKey();
            List<CartItem> cartItemList = getCartItemList(key);
            cart.setItems(cartItemList);

        } else {
            // 登陆了
            String key = CART_PREFIX + userInfoTo.getUserId();
            // 如果临时购物车的数据还没有进行合并【合并购物车】
            String tempKey = CART_PREFIX + userInfoTo.getUserKey();
            List<CartItem> tempItemList = getCartItemList(tempKey);
            if (CollUtil.isNotEmpty(tempItemList)) {
                assert tempItemList != null;
                for (CartItem cartItem : tempItemList) {
                    addToCart(cartItem.getSkuId(), cartItem.getCount());
                }
                // 清除临时购物车数据
                clearCart(tempKey);

            }

            // 获取登陆后的购物车数据【包含合并过来的临时购物车数据，和登陆后的购物车数据
            List<CartItem> itemList = getCartItemList(key);
            cart.setItems(itemList);

        }

        return cart;
    }

    @Override
    public void clearCart(String key) {
        stringRedisTemplate.delete(key);
    }

    @Override
    public void checkCartItem(Long skuId, Integer check) {
        CartItem cartItem = getCartItem(skuId);
        cartItem.setCheck(check == 0);
        BoundHashOperations<String, String, String> ops = getCartOps();
        ops.put(skuId.toString(), JSONUtil.toJsonStr(cartItem));
    }

    @Override
    public List<CartItem> getUserCartItems() {
        UserInfoTo userInfoTo = CartInterceptor.THREAD_LOCAL.get();
        if (userInfoTo == null || userInfoTo.getUserId() == null) {
            return Collections.emptyList();
        }
        String key = CART_PREFIX + userInfoTo.getUserId();
        List<CartItem> cartItemList = getCartItemList(key);

        return cartItemList.stream().filter(CartItem::getCheck).peek(cart -> {
            // 查询最新price
            cart.setPrice(productFeignService.getSkuPrice(cart.getSkuId()));
        }).collect(Collectors.toList());
    }

    private List<CartItem> getCartItemList(String key) {
        BoundHashOperations<String, String, String> ops = stringRedisTemplate.boundHashOps(key);

        List<String> list = ops.values();
        if (CollUtil.isNotEmpty(list)) {
            return list.stream().map(item -> JSONUtil.toBean(item, CartItem.class)).collect(Collectors.toList());
        }
        return Collections.emptyList();
    }


    /**
     * 获取到我们要操作的购物车
     *
     * @return
     */
    public BoundHashOperations<String, String, String> getCartOps() {
        UserInfoTo userInfoTo = CartInterceptor.THREAD_LOCAL.get();

        String key;
        if (userInfoTo.getUserId() != null) {
            key = CART_PREFIX + userInfoTo.getUserId();
        } else {
            key = CART_PREFIX + userInfoTo.getUserKey();
        }
        return stringRedisTemplate.boundHashOps(key);

    }

}
